<template>
  <div class="tinymce-container" :class="{fullscreen:fullscreen}">
    <textarea :id="tinymceId" class="tinymce-textarea" />
    <div class="editor-custom-btn-container">
      <div class="editor-upload-btn" @click="handleUploadImage">
        <el-upload
          :action="uploadUrl"
          :headers="headers"
          :show-file-list="false"
          :before-upload="beforeUpload"
          :on-success="handleSuccess"
          :on-error="handleError"
          class="editor-upload"
          accept="image/png, image/gif, image/jpeg, image/bmp, image/x-icon"
        >
          <el-button size="small" type="primary">
            <i class="el-icon-upload" /> 上传图片
          </el-button>
        </el-upload>
      </div>
    </div>
  </div>
</template>

<script>
import { defineComponent, ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { ElMessage } from 'element-plus'
import tinymce from 'tinymce/tinymce'
import 'tinymce/themes/silver'
import 'tinymce/icons/default'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/link'
import 'tinymce/plugins/image'
import 'tinymce/plugins/table'
import 'tinymce/plugins/wordcount'
import 'tinymce/plugins/fullscreen'

export default defineComponent({
  name: 'Tinymce',
  props: {
    modelValue: {
      type: String,
      default: ''
    },
    height: {
      type: [Number, String],
      required: false,
      default: 360
    },
    menubar: {
      type: String,
      default: 'file edit insert view format table'
    },
    toolbar: {
      type: [String, Array],
      required: false,
      default: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image | removeformat'
    },
    uploadUrl: {
      type: String,
      default: ''
    },
    headers: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['update:modelValue', 'change'],
  setup(props, { emit }) {
    const tinymceId = `vue-tinymce-${Date.now()}`
    const fullscreen = ref(false)
    let editor = null

    const initTinymce = () => {
      tinymce.init({
        selector: `#${tinymceId}`,
        height: props.height,
        body_class: 'panel-body',
        object_resizing: false,
        toolbar: props.toolbar,
        menubar: props.menubar,
        plugins: [
          'advlist autolink lists link image table wordcount fullscreen'
        ],
        language: 'zh_CN',
        end_container_on_empty_block: true,
        powerpaste_word_import: 'clean',
        code_dialog_height: 450,
        code_dialog_width: 1000,
        advlist_bullet_styles: 'square',
        advlist_number_styles: 'default',
        default_link_target: '_blank',
        link_title: false,
        nonbreaking_force_tab: true,
        init_instance_callback: editor => {
          if (props.modelValue) {
            editor.setContent(props.modelValue)
          }
          editor.on('NodeChange Change KeyUp SetContent', () => {
            const content = editor.getContent()
            emit('update:modelValue', content)
            emit('change', content)
          })
        },
        setup: editor => {
          editor = editor
        },
        images_upload_handler: (blobInfo, success, failure) => {
          const formData = new FormData()
          formData.append('file', blobInfo.blob())
          // 实现图片上传逻辑
        }
      })
    }

    const destroyTinymce = () => {
      if (tinymce.get(tinymceId)) {
        tinymce.get(tinymceId).destroy()
      }
    }

    const handleUploadImage = file => {
      const isImage = file.type.indexOf('image/') > -1
      if (!isImage) {
        ElMessage.error('只能上传图片!')
        return false
      }
      return true
    }

    const handleSuccess = (response, file) => {
      // 处理上传成功
      ElMessage.success('上传成功')
      const url = response.url
      editor && editor.insertContent(`<img src="${url}" />`) 
    }

    const handleError = () => {
      ElMessage.error('上传失败')
    }

    onMounted(() => {
      nextTick(() => {
        initTinymce()
      })
    })

    onBeforeUnmount(() => {
      destroyTinymce()
    })

    return {
      tinymceId,
      fullscreen,
      handleUploadImage,
      handleSuccess,
      handleError
    }
  }
})
</script>

<style lang="scss" scoped>
.tinymce-container {
  position: relative;
  line-height: normal;

  .tinymce-textarea {
    visibility: hidden;
    z-index: -1;
  }

  &.fullscreen {
    z-index: 10000;
    position: fixed;
    top: 0;
    left: 0;
    height: 100vh;
  }
}

.editor-custom-btn-container {
  position: absolute;
  right: 15px;
  top: 18px;
  z-index: 2005;
}

.editor-upload-btn {
  display: inline-block;
}
</style>